import json
import os
from django.db import models
from django.contrib.auth.models import AbstractBaseUser, BaseUserManager, PermissionsMixin
from django.core.exceptions import ValidationError
from django import forms
from django.contrib.auth.hashers import make_password


class RbacUserManager(BaseUserManager):
    """自定义用户管理器"""
    
    def create_user(self, email, username, password=None, **extra_fields):
        if not email:
            raise ValueError('用户必须有邮箱地址')
        if not username:
            raise ValueError('用户必须有用户名')
        
        email = self.normalize_email(email)
        user = self.model(email=email, username=username, **extra_fields)
        user.set_password(password)
        user.save(using=self._db)
        return user
    
    def create_superuser(self, email, username, password=None, **extra_fields):
        extra_fields.setdefault('is_staff', True)
        extra_fields.setdefault('is_superuser', True)
        extra_fields.setdefault('is_active', True)
        
        return self.create_user(email, username, password, **extra_fields)


class Permission(models.Model):
    """权限模型"""
    name = models.CharField(max_length=100, verbose_name="权限名称")
    code = models.CharField(max_length=50, unique=True, verbose_name="权限代码")
    description = models.TextField(blank=True, null=True, verbose_name="权限描述")
    group = models.CharField(max_length=50, verbose_name="权限分组")
    created_at = models.DateTimeField(auto_now_add=True, verbose_name="创建时间")
    updated_at = models.DateTimeField(auto_now=True, verbose_name="更新时间")

    class Meta:
        verbose_name = "权限"
        verbose_name_plural = "权限"
        ordering = ['group', 'name']

    def __str__(self):
        return f"{self.group} - {self.name}"


class Role(models.Model):
    """角色模型"""
    name = models.CharField(max_length=50, unique=True, verbose_name="角色名称")
    code = models.CharField(max_length=30, unique=True, verbose_name="角色代码")
    description = models.TextField(blank=True, null=True, verbose_name="角色描述")
    is_active = models.BooleanField(default=True, verbose_name="是否启用")
    is_system = models.BooleanField(default=False, verbose_name="是否系统角色")
    permissions = models.ManyToManyField(
        Permission, 
        through='RolePermission',
        verbose_name="权限"
    )
    created_at = models.DateTimeField(auto_now_add=True, verbose_name="创建时间")
    updated_at = models.DateTimeField(auto_now=True, verbose_name="更新时间")

    class Meta:
        verbose_name = "角色"
        verbose_name_plural = "角色"
        ordering = ['name']

    def __str__(self):
        return self.name

    def get_permission_codes(self):
        """获取角色的所有权限代码"""
        return list(self.permissions.values_list('code', flat=True))


class RolePermission(models.Model):
    """角色权限关联模型"""
    role = models.ForeignKey(Role, on_delete=models.CASCADE)
    permission = models.ForeignKey(Permission, on_delete=models.CASCADE)
    granted_at = models.DateTimeField(auto_now_add=True, verbose_name="授权时间")
    granted_by = models.ForeignKey(
        'RbacUser', 
        on_delete=models.SET_NULL, 
        null=True, 
        blank=True,
        verbose_name="授权人"
    )

    class Meta:
        unique_together = ('role', 'permission')
        verbose_name = "角色权限"
        verbose_name_plural = "角色权限"

    def __str__(self):
        return f"{self.role.name} - {self.permission.name}"


class RbacUser(AbstractBaseUser, PermissionsMixin):
    """RBAC用户模型"""
    username = models.CharField(max_length=150, unique=True, verbose_name="用户名")
    email = models.EmailField(max_length=255, unique=True, verbose_name="邮箱")
    first_name = models.CharField(max_length=30, blank=True, verbose_name="名")
    last_name = models.CharField(max_length=30, blank=True, verbose_name="姓")
    
    # 新的角色系统 - 使用多对多关系
    roles = models.ManyToManyField(
        Role,
        through='UserRole',
        through_fields=('user', 'role'),  # 指定使用的字段
        blank=True,
        verbose_name="角色"
    )
    
    is_active = models.BooleanField(default=True, verbose_name="是否激活")
    is_staff = models.BooleanField(default=False, verbose_name="是否员工")
    date_joined = models.DateTimeField(auto_now_add=True, verbose_name="加入时间")
    last_login = models.DateTimeField(null=True, blank=True, verbose_name="最后登录")

    objects = RbacUserManager()

    USERNAME_FIELD = 'email'
    REQUIRED_FIELDS = ['username']

    # 添加 related_name 参数以避免与 auth.User 的字段冲突
    groups = models.ManyToManyField(
        'auth.Group',
        verbose_name='groups',
        blank=True,
        help_text='The groups this user belongs to. A user will get all permissions granted to each of their groups.',
        related_name="rbac_user_groups",
        related_query_name="rbac_user",
    )
    user_permissions = models.ManyToManyField(
        'auth.Permission',
        verbose_name='user permissions',
        blank=True,
        help_text='Specific permissions for this user.',
        related_name="rbac_user_permissions",
        related_query_name="rbac_user",
    )

    class Meta:
        verbose_name = "用户"
        verbose_name_plural = "用户"
        
    def clean(self):
        # 检查用户名唯一性（修改时需要排除当前实例）
        if self.pk:
            if RbacUser.objects.filter(username=self.username).exclude(pk=self.pk).exists():
                raise ValidationError({'username': '用户名已存在'})
        else:
            if RbacUser.objects.filter(username=self.username).exists():
                raise ValidationError({'username': '用户名已存在'})

    def __str__(self):
        return self.username

    def has_permission(self, permission_code):
        """检查用户是否具有指定权限"""
        # 超级用户拥有所有权限
        if self.is_superuser:
            return True
            
        # 检查通过角色分配的权限
        return self.roles.filter(
            rolepermission__permission__code=permission_code,
            is_active=True
        ).exists()

    def get_all_permissions(self):
        """获取用户的所有权限"""
        return Permission.objects.filter(
            rolepermission__role__in=self.roles.filter(is_active=True)
        ).distinct()

    def get_full_name(self):
        """获取全名"""
        return f"{self.last_name}{self.first_name}".strip()

    def get_short_name(self):
        """获取简短名称"""
        return self.first_name


class UserRole(models.Model):
    """用户角色关联模型"""
    user = models.ForeignKey(RbacUser, on_delete=models.CASCADE)
    role = models.ForeignKey(Role, on_delete=models.CASCADE)
    assigned_at = models.DateTimeField(auto_now_add=True, verbose_name="分配时间")
    assigned_by = models.ForeignKey(
        RbacUser,
        on_delete=models.SET_NULL,
        null=True,
        blank=True,
        related_name='assigned_roles',
        verbose_name="分配人"
    )

    class Meta:
        unique_together = ('user', 'role')
        verbose_name = "用户角色"
        verbose_name_plural = "用户角色"

    def __str__(self):
        return f"{self.user.username} - {self.role.name}"


class Menu(models.Model):
    """菜单模型"""
    name = models.CharField(max_length=100, verbose_name="菜单名称")
    code = models.CharField(max_length=50, unique=True, verbose_name="菜单代码")
    description = models.TextField(blank=True, null=True, verbose_name="菜单描述")
    icon = models.CharField(max_length=50, default='fas fa-cube', verbose_name="菜单图标")
    url = models.CharField(max_length=200, verbose_name="菜单链接")
    color = models.CharField(max_length=20, default='primary', verbose_name="菜单颜色")
    is_active = models.BooleanField(default=True, verbose_name="是否启用")
    sort_order = models.IntegerField(default=0, verbose_name="排列顺序")
    
    # 权限控制
    required_roles = models.ManyToManyField(
        Role,
        blank=True,
        verbose_name="需要的角色",
        help_text="留空表示所有用户都可以看到"
    )
    
    created_at = models.DateTimeField(auto_now_add=True, verbose_name="创建时间")
    updated_at = models.DateTimeField(auto_now=True, verbose_name="更新时间")

    class Meta:
        verbose_name = "菜单"
        verbose_name_plural = "菜单"
        ordering = ['sort_order', 'name']

    def __str__(self):
        return self.name

    def can_access(self, user):
        """检查用户是否可以访问该菜单"""
        # 超级用户可以访问所有菜单
        if user.is_superuser:
            return True
        
        # 如果没有设置角色限制，所有用户都可以访问
        if not self.required_roles.exists():
            return True
        
        # 检查用户是否具有需要的角色
        user_roles = user.roles.filter(is_active=True)
        return self.required_roles.filter(id__in=user_roles.values_list('id', flat=True)).exists()


class RbacUserModelForm(forms.ModelForm):
    """用户模型表单"""
    roles = forms.ModelMultipleChoiceField(
        queryset=None,  # 将在__init__中设置
        widget=forms.CheckboxSelectMultiple,
        required=False,
        label="角色"
    )
    
    class Meta:
        model = RbacUser
        fields = ['username', 'email', 'first_name', 'last_name', 'password']
        widgets = {
            'password': forms.PasswordInput(),
        }

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        # 设置活跃的角色选项
        self.fields['roles'].queryset = Role.objects.filter(is_active=True)
        
        # 如果是编辑模式，设置当前用户的角色
        if self.instance.pk:
            self.fields['roles'].initial = self.instance.roles.all()
        
        for name, field in self.fields.items():
            if name != 'roles':  # roles字段使用CheckboxSelectMultiple，不需要form-control类
                field.widget.attrs['class'] = 'form-control'

    def clean(self):
        cleaned_data = super().clean()
        # 自定义验证逻辑
        username = cleaned_data.get('username')
        if username:
            if self.instance.pk:
                # 编辑模式：排除当前实例
                if RbacUser.objects.filter(username=username).exclude(pk=self.instance.pk).exists():
                    raise ValidationError({'username': '用户名已存在'})
            else:
                # 新增模式
                if RbacUser.objects.filter(username=username).exists():
                    raise ValidationError({'username': '用户名已存在'})
        return cleaned_data
    
    def save(self, commit=True):
        user = super().save(commit=False)
        if commit:
            # 处理密码
            if self.cleaned_data.get('password'):
                user.set_password(self.cleaned_data['password'])
            user.save()
            # 保存角色关系
            if 'roles' in self.cleaned_data:
                user.roles.set(self.cleaned_data['roles'])
        return user


class PermissionManager:
    """权限管理器 - 用于初始化系统权限和角色"""
    
    # 预定义的系统权限
    DEFAULT_PERMISSIONS = [
        # 用户管理权限
        {'name': '查看用户列表', 'code': 'user.list', 'group': '用户管理', 'description': '可以查看所有用户信息'},
        {'name': '添加用户', 'code': 'user.add', 'group': '用户管理', 'description': '可以创建新用户'},
        {'name': '编辑用户', 'code': 'user.edit', 'group': '用户管理', 'description': '可以修改用户信息'},
        {'name': '删除用户', 'code': 'user.delete', 'group': '用户管理', 'description': '可以删除用户'},
        {'name': '管理用户角色', 'code': 'user.manage_roles', 'group': '用户管理', 'description': '可以为用户分配角色'},
        
        # 角色管理权限
        {'name': '查看角色列表', 'code': 'role.list', 'group': '角色管理', 'description': '可以查看所有角色'},
        {'name': '添加角色', 'code': 'role.add', 'group': '角色管理', 'description': '可以创建新角色'},
        {'name': '编辑角色', 'code': 'role.edit', 'group': '角色管理', 'description': '可以修改角色信息'},
        {'name': '删除角色', 'code': 'role.delete', 'group': '角色管理', 'description': '可以删除角色'},
        {'name': '管理角色权限', 'code': 'role.manage_permissions', 'group': '角色管理', 'description': '可以为角色分配权限'},
        
        # 系统管理权限
        {'name': '系统配置', 'code': 'system.config', 'group': '系统管理', 'description': '可以修改系统配置'},
        {'name': '查看系统统计', 'code': 'system.stats', 'group': '系统管理', 'description': '可以查看系统统计信息'},
        {'name': '查看审计日志', 'code': 'system.audit', 'group': '系统管理', 'description': '可以查看系统审计日志'},
    ]
    
    # 预定义的系统角色
    DEFAULT_ROLES = [
        {
            'name': '超级管理员',
            'code': 'super_admin',
            'description': '具有所有权限的超级管理员',
            'is_system': True,
            'permissions': [p['code'] for p in DEFAULT_PERMISSIONS]  # 所有权限
        },
        {
            'name': '管理员',
            'code': 'admin',
            'description': '系统管理员，具有大部分管理权限',
            'is_system': True,
            'permissions': [
                'user.list', 'user.add', 'user.edit', 'user.manage_roles',
                'role.list', 'system.stats'
            ]
        },
        {
            'name': '普通用户',
            'code': 'user',
            'description': '普通系统用户，具有基本权限',
            'is_system': True,
            'permissions': []  # 根据具体业务需求添加
        }
    ]
    
    @classmethod
    def init_permissions(cls):
        """初始化系统权限"""
        for perm_data in cls.DEFAULT_PERMISSIONS:
            Permission.objects.get_or_create(
                code=perm_data['code'],
                defaults={
                    'name': perm_data['name'],
                    'group': perm_data['group'],
                    'description': perm_data['description']
                }
            )
        print(f"初始化了 {len(cls.DEFAULT_PERMISSIONS)} 个权限")
    
    @classmethod
    def init_roles(cls):
        """初始化系统角色"""
        for role_data in cls.DEFAULT_ROLES:
            role, created = Role.objects.get_or_create(
                code=role_data['code'],
                defaults={
                    'name': role_data['name'],
                    'description': role_data['description'],
                    'is_system': role_data['is_system']
                }
            )
            
            # 清除旧权限并设置新权限
            role.permissions.clear()
            for perm_code in role_data['permissions']:
                try:
                    permission = Permission.objects.get(code=perm_code)
                    RolePermission.objects.get_or_create(
                        role=role,
                        permission=permission
                    )
                except Permission.DoesNotExist:
                    print(f"警告：权限 {perm_code} 不存在")
        
        print(f"初始化了 {len(cls.DEFAULT_ROLES)} 个角色")
    
    @classmethod
    def init_all(cls):
        """初始化所有数据"""
        cls.init_permissions()
        cls.init_roles()